package com.cgs.query.monitor

import com.cgs.query.monitor.metrics.CodahaleMetricsHelper
import com.cgs.query.monitor.metrics.MeterInfo
import com.cgs.query.monitor.metrics.MetricsHelper
import com.cgs.query.monitor.metrics.ProjectTimerInfo
import com.cgs.query.service.IQueryProjectService
import com.cgs.query.util.Utils
import mu.KotlinLogging
import org.springframework.beans.factory.annotation.Autowired
import java.io.Serializable

private val logger = KotlinLogging.logger { }

/**
 * 监控项目
 */
class ProjectMonitor : MonitorBean<ProjectMonitorObj, ProjectMonitorInfo> {

    @Autowired
    private lateinit var dataSourceMonitor: DataSourceMonitor
    @Autowired
    private lateinit var queryProjectService: IQueryProjectService

    override fun start() {
        logger.info { ">>>>>>>>>>>>>>>>开启项目监控" }
    }

    override fun stop() {
        logger.info { ">>>>>>>>>>>>>>>>关闭项目监控" }
    }

    override fun monitor(obj: ProjectMonitorObj): ProjectMonitorInfo? {
        val timerInfoList = MetricsHelper.INSTANCE.getProjectTimer(obj.projectName)
        val meterInfoList = CodahaleMetricsHelper.INSTANCE.getProjectMeterInfo(obj.projectName)
        val sourceMonitorInfo = dataSourceMonitor.monitor(SourceMonitorObj(
                Utils.notNull(queryProjectService.findByName(obj.projectName), "找不到数据源${obj.projectName}")
                        .sourceId))
        var sum = 0L
        var fail = 0L
        timerInfoList?.map {
            sum += it.count
            fail += it.fCount ?: 0
        }
        return ProjectMonitorInfo(timerInfoList, meterInfoList, sourceMonitorInfo, ProjectBaseInfo(sum, fail))
    }

    override fun clean(obj: ProjectMonitorObj) {
        MetricsHelper.INSTANCE.registry.find("server").tag("project", obj.projectName).meters().forEach {
            MetricsHelper.INSTANCE.registry.remove(it)?.close()
        }
    }
}


/**
 * 需要展示对sql的监控
 * 项目状态的监控
 */
class ProjectMonitorInfo(
        val timerInfoList: List<ProjectTimerInfo>? = listOf(),
        val meterInfoList: List<MeterInfo>? = listOf(),
        val sourceMonitorInfo: SourceMonitorInfo? = null,
        val baseInfo: ProjectBaseInfo
) : MonitorInfo()

data class ProjectMonitorObj(
        /**项目名称*/
        val projectName: String
) : MonitorObj()

class ProjectBaseInfo(
        /**总调用次数*/
        val count: Long,
        /**失败调用次数*/
        val fCount: Long?
) : Serializable